package cn.edu.gzgs.config;

import cn.edu.gzgs.config.security.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager; // Needed for AuthenticationManager bean if custom auth provider is used, or for explicit password grant types
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; // To get AuthenticationManager
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; // For csrf and httpBasic disable
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity // 启用 Spring Security 的 Web 安全功能
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final UserDetailsService userDetailsService; // Spring 会注入 UserDetailsServiceImpl
    // 可以选择注入一个自定义的 AuthenticationEntryPoint 处理认证失败
    // private final JwtAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter, 
                          UserDetailsService userDetailsService) {
                          // JwtAuthenticationEntryPoint unauthorizedHandler) {
        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
        this.userDetailsService = userDetailsService;
        // this.unauthorizedHandler = unauthorizedHandler;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            // 禁用 CSRF 保护，因为我们使用 JWT，通常是无状态的
            .csrf(AbstractHttpConfigurer::disable)
            // 配置请求授权规则
            .authorizeHttpRequests(authorize -> authorize
                // 明确允许对登录接口、API文档等公共路径的匿名访问
                .requestMatchers("/api/auth/login").permitAll()
                .requestMatchers("/api/captcha").permitAll()
                .requestMatchers("/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**", "/webjars/**").permitAll()
                // 允许根路径和静态资源
                .requestMatchers("/", "/index.html", "/favicon.ico", "/static/**").permitAll()
                // 允许WebSocket连接（WebSocket握手无法携带Authorization头）
                .requestMatchers("/websocket").permitAll()
                // 对于所有其他请求，要求用户必须已经认证
                .anyRequest().authenticated()
            )
            // 配置会话管理为无状态 (STATELESS)，因为我们不依赖会话
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            // （可选）配置自定义的认证入口点，用于处理认证失败（例如，返回401 JSON响应）
            // .exceptionHandling(exceptions -> exceptions.authenticationEntryPoint(unauthorizedHandler))
            // 将我们的自定义 JWT 认证过滤器添加到 Spring Security 过滤器链中
            // 它应该在标准的 UsernamePasswordAuthenticationFilter 之前执行
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        // Spring Security 6 不再需要显式配置 AuthenticationManagerBuilder
        // 它会使用 UserDetailsService 和 PasswordEncoder (已在主应用类中配置) 自动配置

        return http.build();
    }

    // 如果需要显式地暴露 AuthenticationManager bean (例如，用于某些旧的 OAuth2 配置或手动认证)
    // Spring Security 6.x 及以上版本推荐通过 AuthenticationConfiguration 获取
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    // 如果不使用 AuthenticationConfiguration, 并且需要一个 AuthenticationProvider, 可以这样配置 (但通常 UserDetailsService + PasswordEncoder 就够了)
    /*
    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder); // passwordEncoder bean is defined elsewhere
        return authProvider;
    }
    */
} 